package com.ericsson.enap.modules.ebmLog.service.impl.vgc;

import com.ericsson.common.domain.CollectBizTypeEnum;
import com.ericsson.common.domain.NetTypeEnum;
import com.ericsson.common.pojo.FTPInfoVO;
import com.ericsson.common.util.DateUtils;
import com.ericsson.common.util.LogFileName;
import com.ericsson.common.util.LoggerUtils;
import com.ericsson.config.datasource.DynamicDataSourceContextHolder;
import com.ericsson.config.enums.DataSourceType;
import com.ericsson.enap.modules.ebmLog.config.EbmParam;
import com.ericsson.enap.modules.ebmLog.entity.vgc.VgcEbmEventVO;
import com.ericsson.enap.modules.ebmLog.entity.vgc.VgcEbmTaskParam;
import com.ericsson.enap.modules.ebmLog.mapper.vgc.VgcEbmLogMapper;
import com.ericsson.enap.modules.ebmLog.service.vgc.VgcEbmLogService;
import com.ericsson.enap.modules.ebmLog.task.EbmDownLoadTask;
import com.ericsson.enap.modules.ebmLog.task.vgc.VgcEbmExecuteScriptTask;
import com.ericsson.enap.modules.ebmLog.task.vgc.VgcEbmStatisticAndLoadTask;
import com.ericsson.enap.modules.monitor.entity.SysDictData;
import com.ericsson.enap.modules.monitor.mapper.SysDictDataMapper;
import com.ericsson.enap.modules.sys.entity.EnipNetelement;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

import static com.ericsson.enap.modules.ebmLog.constant.VgcEbmConstant.AMF;
import static com.ericsson.enap.modules.ebmLog.utils.VgcEbmLogUtil.*;

/**
 * @description:
 * @author: wangjingshi
 * @create: 2021-11-09 12:33
 */
@Service
public class VgcEbmLogServiceImpl implements VgcEbmLogService {

    private final Logger log = LoggerUtils.Logger(LogFileName.VgcEbmLogJob);
    @Autowired
    private SysDictDataMapper sysDictDataMapper;
    @Autowired
    private VgcEbmLogMapper vgcEbmLogMapper;
    @Value("${collectorIp}")
    private String collectorIp;
    @Autowired
    private EbmParam ebmParam;

    /**
     *
     * @param delay 延时
     * @param ebmPath ebm基础路径
     * @return 该服务器所采集的网元集合
     */
    @Override
    public List<EnipNetelement> DownLoadEbmFiles(Integer delay,String ebmPath,String _remotePath) {
        //1.查询当前采集器配置了哪些网元需要进行下载,业务代码: 17是5gc ebmLog多维业务
        Integer bizType = Integer.parseInt(CollectBizTypeEnum.VGCEbmLogFileParse.value());
        log.info("======= bizType:"+bizType+" ======= collectorIp:"+collectorIp);
        List<EnipNetelement> list = vgcEbmLogMapper.queryNetelementList(bizType,collectorIp);
        log.info("======= EnipNetelement list:"+list.size());
        CountDownLatch latch = new CountDownLatch(list.size());
        //2.多线程处理下载的网元，最后通过线程计数器的方式保证所有网元ebm文件下载完成后进行解析
        FTPInfoVO fTPInfoVO;
        for(int i = 0;i<list.size();i++){
            fTPInfoVO = new FTPInfoVO();
            fTPInfoVO.setHost(list.get(i).getIp4());
            fTPInfoVO.setPort(21);
            fTPInfoVO.setUserName(list.get(i).getUsername());
            fTPInfoVO.setPassword(list.get(i).getPassword());
            fTPInfoVO.setNetElementID(list.get(i).getId());
            String remotePath = _remotePath + File.separator + AMF + File.separator + list.get(i).getId() + File.separator;
            String localPath = ebmPath + list.get(i).getId() + File.separator;
            EbmDownLoadTask ebmDownLoadTask = new EbmDownLoadTask(fTPInfoVO,remotePath,localPath,latch,delay);
            Thread t = new Thread(ebmDownLoadTask);
            t.start();
        }
        try {
            latch.await();
            log.info("===== All netelements download ebm files end! =====");
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }
        return list;
    }

    /**
     *
     * @param list ebm多维采集的网元
     * @param ebmPath ebm基础路径
     * @return AMF类型事件map集合
     */
    @Override
    public Map<String, VgcEbmEventVO> execScriptEbmFiles(List<EnipNetelement> list,String ebmPath) {
        Map<String, VgcEbmEventVO> eventMap = vgcEbmLogMapper.eventMap(NetTypeEnum.AMF.value());
        CountDownLatch latch = new CountDownLatch(list.size());
        for(int i=0;i<list.size();i++) {
            String localPath = ebmPath + list.get(i).getId() + File.separator;
            VgcEbmExecuteScriptTask task = new VgcEbmExecuteScriptTask(String.valueOf(list.get(i).getId()),localPath,latch);
            new Thread(task).start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        } finally {
            log.info("===== All netelements exec ebm csv files end! =====");
        }
        return eventMap;
    }

    /**
     *
     * @param map ebm事件map
     * @param delay ebm延时
     * @param ebmLogDays ebm文件保存天数
     */
    @Override
    public void dropExpireTables(Map<String, VgcEbmEventVO> map, Integer delay, Integer ebmLogDays, List<EnipNetelement> list) {
        Date date = getDate(delay);
        String cleanDate = DateUtils.beforNumDay(date, -ebmLogDays).replaceAll("-", "_");
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
        for(EnipNetelement net:list){
            for(Map.Entry<String, VgcEbmEventVO> entry:map.entrySet()) {
                String name = entry.getValue().getEvent_type();
                String dropCcTable = cleanDate + "_" +  net.getId() + "_" +name;
                vgcEbmLogMapper.dropEbmLogTable(dropCcTable);
                String dropDimensionTable = dropCcTable + "_dimension";
                vgcEbmLogMapper.dropEbmLogTable(dropDimensionTable);
                String dropChartTable = dropCcTable + "_chart";
                vgcEbmLogMapper.dropEbmLogTable(dropChartTable);
                if(name.equals("amf_paging")){
                    String dropSubTable = dropCcTable + "_sub";
                    vgcEbmLogMapper.dropEbmLogTable(dropSubTable);
                }
                String dropNTacTable = dropCcTable + "_n_tac";
                vgcEbmLogMapper.dropEbmLogTable(dropNTacTable);
                String dropNciTable = dropCcTable + "_nci";
                vgcEbmLogMapper.dropEbmLogTable(dropNciTable);
            }
        }
        DynamicDataSourceContextHolder.clearDataSourceType();
    }

    /**
     *
     * @param map ebm事件map
     * @param delay ebm延时
     */
    @Override
    public void createTables(Map<String, VgcEbmEventVO> map,Integer delay,List<EnipNetelement> list) {
        String dateTime = DateUtils.getEbmLogStartMinDateTime(15+ delay);
        String tableNameTime = dateTime.substring(0,10).replaceAll("-", "_");
        Map<String, String> conditionMap = ebmParam.getCondition();
        StringBuffer sb_ccScc,sb_dimension,sb_chart,sb_paging_sub,sb_n_tac,sb_nci;
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
        for(EnipNetelement net:list){
            for(Map.Entry<String,VgcEbmEventVO> entry:map.entrySet()){
                String eventType = entry.getKey();//事件类型
                String[] conditionArrs = {};
                if(conditionMap.containsKey(eventType)){
                    conditionArrs = conditionMap.get(eventType).split(",");
                }
                sb_ccScc = getCcSccSql(tableNameTime, net, eventType, conditionArrs);
                vgcEbmLogMapper.createTable(sb_ccScc.toString());
                String[] dimensionArr = ebmParam.getDimensions().get(eventType).split(",");
                sb_dimension = getDimensionSql(tableNameTime, net, eventType, conditionArrs,dimensionArr);
                vgcEbmLogMapper.createTable(sb_dimension.toString());
                sb_chart = getChartSql(tableNameTime, net, eventType, conditionArrs);
                vgcEbmLogMapper.createTable(sb_chart.toString());
                sb_n_tac = getNTacSql(tableNameTime, net, eventType);
                vgcEbmLogMapper.createTable(sb_n_tac.toString());
                sb_nci = getNciSql(tableNameTime, net, eventType);
                vgcEbmLogMapper.createTable(sb_nci.toString());

            }
            sb_paging_sub = getPagingSubSql(tableNameTime, net);
            vgcEbmLogMapper.createTable(sb_paging_sub.toString());
        }
        DynamicDataSourceContextHolder.clearDataSourceType();
    }

    @Override
    public void statisticAndLoadDb(List<EnipNetelement> list,Map<String, VgcEbmEventVO> map,String ebmPath,Integer delay) {
        Map<String,Integer> dnnMap = this.getDictMap("enip_ebm_dnn");
        Map<Integer,String> _dnnMap = this.getDictReverseMap("enip_ebm_dnn");

        Map<String,Integer> srtypeMap = this.getDictMap("enip_ebm_service_request_type");
        Map<Integer,String> _srtypeMap = this.getDictReverseMap("enip_ebm_service_request_type");

        Map<String,Integer> srtriggerMap = this.getDictMap("enip_ebm_service_request_trigger");
        Map<Integer,String> _srtriggerMap = this.getDictReverseMap("enip_ebm_service_request_trigger");

        Map<String,Integer> handoverMap = this.getDictMap("enip_ebm_handover_type");

        Map<String,Integer> deregistartionMap = this.getDictMap("enip_ebm_deregistration_trigger");
        Map<Integer,String> _deregistartionMap = this.getDictReverseMap("enip_ebm_deregistration_trigger");

        Map<String,Integer> resultTypeMap = this.getDictMap("enip_ebm_result_type");
        VgcEbmTaskParam param;
        //外层按照网元拆分多线程执行核心任务
        CountDownLatch latch = new CountDownLatch(list.size());
        for(EnipNetelement enipNetelement:list){
            String localPath = ebmPath + enipNetelement.getId() + File.separator;
            String dateTime = DateUtils.getEbmLogStartMinDateTime(15+delay);
            param = new VgcEbmTaskParam();
            param.setNetId(enipNetelement.getId());
            param.setDateTime(dateTime);
            param.setEbmParam(ebmParam);
            param.setLocalPath(localPath);
            param.setVgcEbmLogMapper(vgcEbmLogMapper);
            param.setDnnMap(dnnMap);
            param.setSrtypeMap(srtypeMap);
            param.setSrtriggerMap(srtriggerMap);
            param.setHandoverMap(handoverMap);
            param.setDeregistartionMap(deregistartionMap);
            param.set_dnnMap(_dnnMap);
            param.set_deregistartionMap(_deregistartionMap);
            param.set_srtriggerMap(_srtriggerMap);
            param.set_srtypeMap(_srtypeMap);
            param.setResultTypeMap(resultTypeMap);
            VgcEbmStatisticAndLoadTask task = new VgcEbmStatisticAndLoadTask(latch,map,param);
            new Thread(task).start();
        }
        try {
            latch.await();
            log.info("===== All netelements statisticAndInsertDB ebm files end! =====");
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }
    }

    private Map<Integer, String> getDictReverseMap(String type) {
        List<SysDictData> list = sysDictDataMapper.selectDictData(type);
        return list.stream().collect(Collectors.toMap(x->Integer.parseInt(x.getDictValue()),SysDictData::getDictLabel, (key1, key2) -> key2));
    }

    @Override
    public Map<String,Integer> getDictMap(String type){
        List<SysDictData> list = sysDictDataMapper.selectDictDataByType(type);
        return list.stream().collect(Collectors.toMap(SysDictData::getDictLabel, x->Integer.parseInt(x.getDictValue()), (key1, key2) -> key2));
    }
}
